/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// TGUI - Texus's Graphical User Interface
// Copyright (C) 2012 Bruno Van de Velde (VDV_B@hotmail.com)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
//    you must not claim that you wrote the original software.
//    If you use this software in a product, an acknowledgment
//    in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
//    and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


#ifndef _TGUI_SLIDER_INCLUDED_
#define _TGUI_SLIDER_INCLUDED_

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

namespace tgui
{
    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    struct TGUI_API Slider : public OBJECT
    {
        /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        /// Default constructor
        /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        Slider();


        /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        /// Copy constructor
        /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        Slider(const Slider& copy);


        /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        /// Destructor
        /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        virtual ~Slider();


        /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        /// Overload of assignment operator
        /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        Slider& operator= (const Slider& right);


        //////////////////////////////////////////////////////////////////////////////////////////////////////
        /// The path to the folder that contains the images.
        /// The folder must also contain an info.txt file, which will give more information about the slider.
        /// 'verticalScroll' might be changed in this function. If you want to change it then do it afterwards.
        //////////////////////////////////////////////////////////////////////////////////////////////////////
        virtual bool load(const std::string pathname);


        //////////////////////////////////////////////////////////////////////////////////////////////////////
        /// Changes the size of the slider. Note that this function will undo all scaling, as it just
        /// calculates the correct scale factors for you. It is an alternative to setScale.
        /// Note that the slider has to be loaded correctly before calling this function.
        //////////////////////////////////////////////////////////////////////////////////////////////////////
        void setSize(float width, float height);


        //////////////////////////////////////////////////////////////////////////////////////////////////////
        /// Returns the size of the slider, unaffected by scaling.
        //////////////////////////////////////////////////////////////////////////////////////////////////////
        Vector2u getSize() const;


        //////////////////////////////////////////////////////////////////////////////////////////////////////
        /// Returns the size of the slider, after the scaling transformation.
        //////////////////////////////////////////////////////////////////////////////////////////////////////
        Vector2f getScaledSize() const;


        //////////////////////////////////////////////////////////////////////////////////////////////////////
        /// Returns the pathname that was used to load the slider.
        /// When the slider has not been loaded yet then this function will return an empty string.
        //////////////////////////////////////////////////////////////////////////////////////////////////////
        std::string getLoadedPathname();


        //////////////////////////////////////////////////////////////////////////////////////////////////////
        /// Set a minimum value. When the value is too small then it will be changed to this minimum.
        /// The default minimum value is 0.
        //////////////////////////////////////////////////////////////////////////////////////////////////////
        virtual void setMinimum(unsigned int minimum);


        //////////////////////////////////////////////////////////////////////////////////////////////////////
        /// Set a maximum value. When the value is too big then it will be changed to this maximum.
        /// The default maximum value is 100.
        //////////////////////////////////////////////////////////////////////////////////////////////////////
        void setMaximum(unsigned int maximum);


        //////////////////////////////////////////////////////////////////////////////////////////////////////
        /// Changes the current value. It can't be smaller than the minimum or bigger than the maximum.
        //////////////////////////////////////////////////////////////////////////////////////////////////////
        virtual void setValue(unsigned int value);


        //////////////////////////////////////////////////////////////////////////////////////////////////////
        /// Changes the direction of the slider. Pass false when you want the slider to lie horizontal.
        //////////////////////////////////////////////////////////////////////////////////////////////////////
        void setVerticalScroll( bool verticalScroll );


        //////////////////////////////////////////////////////////////////////////////////////////////////////
        /// Returns the minimum value, which is 0 by default.
        //////////////////////////////////////////////////////////////////////////////////////////////////////
        unsigned int getMinimum();


        //////////////////////////////////////////////////////////////////////////////////////////////////////
        /// Returns the maximum value, which is 100 by default.
        //////////////////////////////////////////////////////////////////////////////////////////////////////
        unsigned int getMaximum();


        //////////////////////////////////////////////////////////////////////////////////////////////////////
        /// Returns the current value.
        //////////////////////////////////////////////////////////////////////////////////////////////////////
        unsigned int getValue();


        //////////////////////////////////////////////////////////////////////////////////////////////////////
        /// Find out if the slider is lying vertical or not.
        //////////////////////////////////////////////////////////////////////////////////////////////////////
        bool getVerticalScroll();


        /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        // These functions are used to receive callback from the EventManager.
        // You normally don't need them, but you can use them to simulate an event.
        /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        virtual bool mouseOnObject(float x, float y);
        virtual void leftMousePressed(float x, float y);
        virtual void leftMouseReleased(float x, float y);
        virtual void mouseMoved(float x, float y);
        virtual void keyPressed(sf::Keyboard::Key key);
        void objectFocused();


        /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    private:

        /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        // Because this struct is derived from sf::Drawable, you can just call the draw function from your sf::RenderTarget.
        // This function will be called and it will draw the slider on the render target.
        /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const;


        /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    public:

        /// Is the slider draw vertically?
        /// Set this boolean to false when the slider should lie horizontal.
        bool verticalScroll;

    protected:

        // When the mouse went down, did it go down on top of the thumb? If so, where?
        bool m_MouseDownOnThumb;
        Vector2f m_MouseDownOnThumbPos;

        unsigned int m_Minimum;
        unsigned int m_Maximum;
        unsigned int m_Value;

        // Is the image vertically?
        bool m_VerticalImage;

        // If this is true then the L, M and R images will be used.
        // If it is false then the slider is just one big image that will be stored in the M image.
        bool m_SplitImage;

        // Is there a separate hover image, or is it a semi-transparent image that is drawn on top of the others?
        bool m_SeparateHoverImage;

        sf::Texture* m_TextureTrackNormal_L;
        sf::Texture* m_TextureTrackHover_L;
        sf::Texture* m_TextureTrackNormal_M;
        sf::Texture* m_TextureTrackHover_M;
        sf::Texture* m_TextureTrackNormal_R;
        sf::Texture* m_TextureTrackHover_R;
        sf::Texture* m_TextureThumbNormal;
        sf::Texture* m_TextureThumbHover;

        sf::Sprite   m_SpriteTrackNormal_L;
        sf::Sprite   m_SpriteTrackHover_L;
        sf::Sprite   m_SpriteTrackNormal_M;
        sf::Sprite   m_SpriteTrackHover_M;
        sf::Sprite   m_SpriteTrackNormal_R;
        sf::Sprite   m_SpriteTrackHover_R;
        sf::Sprite   m_SpriteThumbNormal;
        sf::Sprite   m_SpriteThumbHover;

        // The pathname used to load the slider
        std::string m_LoadedPathname;
    };

    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#endif //_TGUI_SLIDER_INCLUDED_
